<?php

namespace App\Kuafu\Mybank\Service;

use App\Exceptions\BaseException;
use App\Kuafu\Mybank\Model\MybankOrderRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderRecordWithholdMappingsModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRecordModel;
use App\Kuafu\Mybank\Model\MybankOrderWithholdRefundRecordModel;
use App\Kuafu\Mybank\Model\MybankWalletRecordModel;
use App\Kuafu\Order\Model\OrderRecordModel;
use App\Kuafu\Pay\Model\PayStreamModel;
use App\Kuafu\Pay\Service\PayService;
use App\Library\FeiShu\SendFs;
use Exception;
use GuzzleHttp\Exception\GuzzleException;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\Response as ResponseAlias;

/**
 * 协议代扣通知
 */
class MybankOrderWithholdRefundNotifyService
{

    public string $outOrderNo;
    public string $outRefundNo;

    public string $status;
    public string $refundFinishDate;

    public string $refundAmount;
    public string $availableAmount;
    public string $freezeAmount;

    public Model  $withholdRefundModel;
    public Model  $withholdModel;
    public string $errorCode;
    public string $errorDesc;

    public function __construct(array $requestBody)
    {
        $requestBody            = array_filter($requestBody);
        $this->outOrderNo       = $requestBody['OutOrderNo'];
        $this->outRefundNo      = $requestBody['OutRefundNo'];
        $this->status           = $requestBody['Status'];
        $this->refundFinishDate = $requestBody['RefundFinishDate'] ?? '';

        $this->refundAmount    = $requestBody['RefundAmount'] ?? 0;
        $this->availableAmount = $requestBody['AvailableAmount'] ?? 0;
        $this->freezeAmount    = $requestBody['FreezeAmount'] ?? 0;

        $this->errorCode = $requestBody['ErrorCode'] ?? '';
        $this->errorDesc = $requestBody['ErrorDesc'] ?? '';

        $this->initWithholdRecordInfo();
    }


    /**
     * @return void
     */
    public function initWithholdRecordInfo()
    {
        $this->withholdRefundModel = MybankOrderWithholdRefundRecordModel::query()
                                                                         ->where('outRefundNo', $this->outRefundNo)
                                                                         ->first();

        $this->withholdModel = MybankOrderWithholdRecordModel::query()
                                                             ->where('orderNo',
                                                                 $this->withholdRefundModel->relateOrderNo)
                                                             ->with(['billRecordRel', 'orderWithholdMappings'])
                                                             ->where('status',
                                                                 MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS)
                                                             ->first();

    }

    /**
     * @return array|void
     * @throws GuzzleException
     * @throws BaseException
     */

    public function handle()
    {
        if (empty($this->withholdRefundModel)) {
            // TODO 记录异常
            return;
        }

        // 幂等状态判断
        if ($this->isHandled()) {
            return;
        }

        // 更新数据库记录状态
        $this->updateWithholdRecordData();

        // 协议代扣是否完成
        if (!($this->isRefund())) {
            return;
        }

        // 更新 orderRecord 的金额数据
        // 通过退款单号获取到对应的代扣记录, 通过代扣记录找到对应的 orderRecord 记录, 暂时只做 1 笔的退款
        if (empty($this->withholdModel->orderWithholdMappings) || count($this->withholdModel->orderWithholdMappings) > 1) {
            return;
        }
        // 获取 orderRecord 数据
        $orderRecordModel = $this->withholdModel->orderWithholdMappings[0]->orderRecordRel;

        // 判断订单原价等于协议代扣的金额的订单
        if ($orderRecordModel->paidBrokerage != $this->withholdModel->totalAmount) {
            return;
        }

        // 总支付金额
        $payTotalSum = $this->withholdModel->totalAmount;
        // 总退款金额
        $refundTotalSum = $this->withholdRefundModel->getTotalRefundAmountByRefundOrderNo();
        // 净支付金额
        $netPaidAmount = $payTotalSum - $refundTotalSum;

        // OrderRecord 订单退款状态
        $orderRecordModel->refundStatus  = MybankOrderRecordModel::REFUND_STATUS_REFUNDED;
        $orderRecordModel->netPaidAmount = $netPaidAmount;
        $orderRecordModel->refundAmount  = $refundTotalSum;
        $orderRecordModel->save();

        $withholdV2Service = (new MybankOrderWithholdV2Service(0, $this->withholdModel->payerId));

        // 钱包添加退款协议代扣的记录
        MybankOrderWithholdService::walletRecordAdd(
            $this->withholdModel->payerId,
            MybankWalletRecordModel::EARNING_TRANS_TYPE,
            $this->refundAmount,
            $withholdV2Service->getMerchantBalance(),
            $orderRecordModel->shopId,
            $this->withholdRefundModel->id,
            MybankWalletRecordModel::RECORD_ID_TYPE_REFUND,
            MybankWalletRecordModel::PLATFORM_TYPE_DEFAULT,
            MybankOrderRecordModel::WALLET_TYPE_SHOW_TYPE_TEXT[$orderRecordModel->type],
            $this->withholdRefundModel->refundOrderNo,
            '',
            $this->withholdRefundModel->refundFinishDate,
            MybankWalletRecordModel::SUCCESS_STATUS,
            MybankWalletRecordModel::SHOW_RECORD
        );

        // 退款成功 @吉连
        /**
         *
         * $outRefundNo 夸父退款订单号
         * $this->refundAmount 此次退款金额
         * $refundTotalSum 该订单总退款金额
         * $netPaidAmount 该订单净支付金额(总支付-总退款)
         *
         */

    }

    /**
     * 是否已经处理
     *
     * @return bool
     */
    private function isHandled(): bool
    {
        // 判断是否已经处理过了
        if (in_array($this->withholdRefundModel->status, [
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL,
            MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS
        ])) {
            return true;
        }

        return false;
    }

    /**
     * 更新数据库记录
     *
     * @return void
     */
    private function updateWithholdRecordData()
    {
        // 更新代扣记录状态
        $this->withholdRefundModel->outOrderNo = $this->outOrderNo;

        if ($this->isRefund()) {
            $this->withholdRefundModel->refundFinishDate = strtotime($this->refundFinishDate);
            $this->withholdRefundModel->status           = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS;
            $this->withholdRefundModel->freezeAmount     = $this->freezeAmount;
            $this->withholdRefundModel->availableAmount  = $this->availableAmount;

        } else {
            $this->withholdRefundModel->status    = MybankOrderWithholdRecordModel::WITHHOLD_STATUS_FAIL;
            $this->withholdRefundModel->errorCode = $this->errorCode;
            $this->withholdRefundModel->errorDesc = $this->errorDesc;

            logMsg('协议代扣退款通知异常', [
                'msg' => $this->errorDesc,

            ], true, true, SendFs::ROBOT_BATCH_BILL_MATCH);

        }

        $this->withholdRefundModel->save();
    }

    /**
     * 是否支付
     *
     * @return bool
     */
    private function isRefund(): bool
    {
        if ($this->status == 'SUCCESS' && !empty($this->refundFinishDate)) {
            return true;
        }
        return false;
    }


    /**
     * 获取账单总支付金额
     *
     * @param string $orderRecordId
     * @return int|mixed
     */
    private function getTotalPaidOrderAmount(string $orderRecordId)
    {
        $payTotalSum = 0;
        MybankOrderRecordWithholdMappingsModel::query()
                                              ->where('orderRecordId', $orderRecordId)
                                              ->with([
                                                  'orderWithholdRecordRel' => function ($query) {
                                                      $query
                                                          ->select(['id', 'outTradeNo', 'status'])
                                                          ->where('status',
                                                              MybankOrderWithholdRecordModel::WITHHOLD_STATUS_SUCCESS);
                                                  }
                                              ])
                                              ->get()
                                              ->each(function ($payItem) use (&$payTotalSum) {
                                                  if (!empty($payItem->orderWithholdRecordRel)) {
                                                      $payTotalSum += $payItem->amount;
                                                  }
                                              });

        return $payTotalSum;
    }

    private function updateOrderRecord(Model $orderWithholdMapping, $payTotalSum)
    {
        $orderWithholdMapping->orderRecordRel->paidBrokerage = $payTotalSum;
        $orderWithholdMapping->orderRecordRel->netPaidAmount = $payTotalSum;
        // 支付完成
        if ($orderWithholdMapping->orderRecordRel->paidBrokerage == $orderWithholdMapping->orderRecordRel->brokerage) {
            $orderWithholdMapping->orderRecordRel->completeAt = time();
            $orderWithholdMapping->orderRecordRel->payStatus  = MybankOrderRecordModel::PAY_STATUS_PAID;
        } else {
            $orderWithholdMapping->orderRecordRel->payStatus = MybankOrderRecordModel::PAY_STATUS_PAYING;
        }
        $orderWithholdMapping->orderRecordRel->save();

    }
}
